package nautilus.tank.model;

import java.awt.Image;
import java.util.Comparator;
import java.util.PriorityQueue;

public abstract class MovingObject extends BattleObject{
	protected volatile float velocityX;
	protected volatile float velocityY;
	protected volatile float velocityZ;
	
	/** this vector is direction of the object */
	protected volatile float[] direction;

	protected volatile int speed;
	protected volatile boolean moving = false;
	protected int sleepingTime = 50;
	protected ObjectRunner objRunner = new ObjectRunner();
	protected Thread movingThread = null;
	
	protected Image[] sprites = null;
	protected int spriteIndex = -1;
	
	protected PriorityQueue<ActionOrder> actions = new PriorityQueue<ActionOrder>(3, new ActionComparator());
	ActionOrder currentAction = null;
	
	public float getVelocityX(){
		return velocityX;
	}
	
	public void setVelocityX(float vx){
		this.velocityX = vx;
	}
	
	public float getVelocityY(){
		return velocityY;
	}
	
	public void setVelocityY(float vy){
		this.velocityY = vy;
	}
	
	public float getVelocityZ(){
		return velocityZ;
	}
	
	public void setVelocityZ(float vz){
		this.velocityZ = vz;
	}
	
	public void setSpeed(int spd){
		this.speed = spd;
		this.sleepingTime = 110 - speed;
	}
	
	public Image[] getSprites(){
		return this.sprites;
	}
	
	public void setSprites(Image[] spr){
		this.sprites = spr;
	}
	
	public float[] getDirection(){
		return direction;
	}
	
	public void setDirection(float[] dir){
		System.arraycopy(dir, 0, direction, 0, 3);
		//velocityY = (float)(Math.sin(direction));
		//velocityX = (float)(Math.cos(direction));
	}
	
	public void startMove() throws InterruptedException{
		if(movingThread != null && movingThread.isAlive()){
			moving = false;
			movingThread.join();
			movingThread = null;
		}
		
		moving = true;
		movingThread = new Thread(objRunner);
		movingThread.start();
	}
	
	@Override
	public void onActionOrder(ActionOrder ao){
		if( currentAction == null || currentAction.isDone() || (currentAction.getPriority()<ao.getPriority())){
			currentAction = ao;
		} else
			actions.add(ao);
			
		try {
			if(!moving)
				startMove();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public void stop() throws InterruptedException{
		moving = false;
		if(movingThread != null && movingThread.isAlive())
			movingThread.join();
	}
	
	public boolean isMoving(){
		return moving;
	}
	
	protected abstract void moveStep();
	
	class ObjectRunner implements Runnable{
		@Override
		public void run() {
			while(moving){
				try {
					//TODO: calculate the speed of object.
					//Scaling the world and find out the sleeping time
					moveStep();
					Thread.sleep(sleepingTime);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

class ActionComparator implements Comparator<ActionOrder>{
	@Override
    public int compare(ActionOrder x, ActionOrder y){
		if(x.getPriority() > y.getPriority())
			return 1;
			
		if(x.getPriority() < y.getPriority())
			return -1;
			
		return 0;
	}
}